package com.apobates.jforum.grief.schema2doc.jdbc.schema;

import com.apobates.jforum.grief.schema2doc.core.SchemaQueryResult;
import com.apobates.jforum.grief.schema2doc.core.SchemaTableStrategy;
import com.apobates.jforum.grief.schema2doc.core.entity.Column;
import com.apobates.jforum.grief.schema2doc.core.entity.Table;
import com.apobates.jforum.grief.schema2doc.core.schema.SchemaDialect;
import org.jooq.DSLContext;
import org.jooq.impl.DSL;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.Optional;
import java.util.stream.Stream;

/**
 * 抽像的导出信息查询执行器
 */
public abstract class AbstractQueryExecutor implements SchemaQueryResult {
    private final DataSource dataSource;
    private final SchemaDialect dialect;

    public AbstractQueryExecutor(DataSource dataSource, SchemaDialect dialect) {
        this.dataSource = dataSource;
        this.dialect = dialect;
    }

    @Override
    public Stream<Table> getAll(Optional<String> dbName, Optional<String> schema, SchemaTableStrategy tableStrategy) throws SQLException {
        try {
            dialect.validate(dbName, schema);
        }catch (IllegalArgumentException e) {
            throw new SQLException(e);
        }
        try(Connection connection = this.dataSource.getConnection()){
            DSLContext context=DSL.using(connection);
            return getTables(context, dbName, schema, tableStrategy);
        }
    }

    @Override
    public Stream<Column> getTableColumn(Table table) throws SQLException {
        try(Connection connection = this.dataSource.getConnection()){
            DSLContext context=DSL.using(connection);
            return getColumns(context, table);
        }
    }

    /**
     * 返回所有导出的表信息
     * @param context DSLContext 实例
     * @param dbName 数据名称
     * @param schema 模式名称
     * @param tableStrategy
     * @return
     * @throws IllegalArgumentException 若数据库名称或模式名称是必须的但不用名抛出
     */
    protected abstract Stream<Table> getTables(DSLContext context, Optional<String> dbName, Optional<String> schema, SchemaTableStrategy tableStrategy) throws IllegalArgumentException;

    /**
     * 返回指定表的所有导出列信息
     * @param context DSLContext 实例
     * @param table 表 实例
     * @return
     */
    protected abstract Stream<Column> getColumns(DSLContext context, Table table);
}
